﻿using System.Security.Claims;
using FlyingHat.Common.Global;
using FlyingHat.Common.Helper;
using FlyingHat.Model.Enums;
using FlyingHat.Model.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace FlyingHat.Web.Controllers
{
    /// <summary>
    /// 基类 [Authorize] 和 [AllowAnonymous] 是基于 就近原则 的，离的越近的 Filter 的权限越高会覆盖掉父级定义的 Filter
    /// Authorize 在进行权限验证的时候会判断当前请求的 Controller 和 Action 上是否有 AllowAnonymous 定义，
    /// 如果有定义则不进行验证，跳过验证，只有在当前请求的 Controller 和 Action 上都没有 AllowAnonymous 时才会进行权限验证。
    /// </summary>
    [Authorize]
    public class BaseController : Controller
    {
        /// <summary>
        /// 当前用户
        /// </summary>
        public UserModel CurrentUser { get; private set; } = new UserModel();

        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            //   CookieAuthenticationDefaults.LoginPath  默认值是 Account/Login
            if (context.HttpContext.User == null || context.HttpContext.User.Identity == null || !context.HttpContext.User.Identity.IsAuthenticated)
            {
                await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                context.Result = Redirect(GlobalConst.LoginPath);
            }
            else
            {

                var user = context.HttpContext.User.Claims.FirstOrDefault(i => i.Type == ClaimTypes.UserData);
                if (string.IsNullOrWhiteSpace(user?.Value))
                {
                    await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                    context.Result = Redirect(GlobalConst.LoginPath);
                }
                else
                {
                    // 以上的验证和[Authorize]验证结果上是相同的，但是不妨碍多写一次。
                    // 反序列化 得到用户对象
                    CurrentUser = SerializeHelper.Deserialize<UserModel>(user.Value) ?? new UserModel();
                    if (CurrentUser.Id == 0)
                    {
                        await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                        context.Result = Redirect(GlobalConst.LoginPath);
                    }
                    else if (CurrentUser.UserStatus != UserStatus.Enable && CurrentUser.UserStatus != UserStatus.Init)
                    {
                        await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                        context.Result = Redirect(GlobalConst.LoginPath);
                    }
                }
            }
            await base.OnActionExecutionAsync(context, next);
        }
    }
}
